package com.kymatrix.kycarbon.xsmd.common.tenant.filter;

import cn.hutool.core.collection.CollUtil;
import com.kymatrix.kycarbon.xsmd.common.business.common.ResultResp;
import com.kymatrix.kycarbon.xsmd.common.springsecurity.LoginUser;
import com.kymatrix.kycarbon.xsmd.common.springsecurity.SecurityUtils;
import com.kymatrix.kycarbon.xsmd.common.util.ServletUtils;
import com.kymatrix.kycarbon.xsmd.common.tenant.config.TenantProperties;
import com.kymatrix.kycarbon.xsmd.common.tenant.context.TenantContextHolder;
import com.kymatrix.kycarbon.xsmd.system.api.service.TenantApi;
import java.io.IOException;
import java.util.Objects;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 多租户 Security Web 过滤器
 * 1. 如果是登陆的用户，校验是否有权限访问该租户，避免越权问题。
 * 2. 如果请求未带租户的编号，检查是否是忽略的 URL，否则也不允许访问。
 * 3. 校验租户是合法，例如说被禁用、到期
 *
 */
@Slf4j
public class TenantSecurityWebFilter extends OncePerRequestFilter {

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    private final TenantProperties tenantProperties;
    private final TenantApi tenantApi;

    public TenantSecurityWebFilter(TenantProperties tenantProperties, TenantApi tenantApi) {
        this.tenantProperties = tenantProperties;
        this.tenantApi = tenantApi;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String tenantId = TenantContextHolder.getTenantId();
        LoginUser user = SecurityUtils.getLoginUser();
        if (user != null) {
            if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) {
                // 当前登录用户的租户 和 请求头中的租户不是同一个
                ServletUtils.writeJSON(response, ResultResp.authError("没有访问该租户的权限"));
                return;
            }
        }

        if (!isIgnoreUrl(request)) {
            if (tenantId == null) {
                ServletUtils.writeJSON(response, ResultResp.authError("租户信息不存在"));
                return;
            }
            if (!tenantApi.validateTenant(tenantId)) {
                ServletUtils.writeJSON(response, ResultResp.authError("租户信息错误"));
                return;
            }
        } else { 
            if (tenantId == null) {
                TenantContextHolder.setIgnore(true);
            }
        }

        chain.doFilter(request, response);
    }

    private boolean isIgnoreUrl(HttpServletRequest request) {
        // 快速匹配，保证性能
        if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) {
            return true;
        }
        // 逐个 Ant 路径匹配
        for (String url : tenantProperties.getIgnoreUrls()) {
            if (pathMatcher.match(url, request.getRequestURI())) {
                return true;
            }
        }
        return false;
    }

}
